ESLint 是现代前端工程化体系中不可或缺的代码质量保障工具。它通过静态分析识别代码中的问题,并提供自动修复能力,确保代码风格的统一性和代码质量的可靠性。
| 维度 | 作用 | 示例 |
|---|---|---|
| 风格统一 | 统一代码格式和书写习惯 | 单双引号、缩进、分号等 |
| 代码优化 | 提升代码简洁性和严谨性 | 禁用未使用变量、要求显式类型标注 |
| 错误预防 | 提前发现潜在问题 | 禁止隐式 any、强制空值检查 |
| 团队协作 | 建立统一的代码规范 | 通过配置文件强制执行规范 |
TypeScript 编译器主要负责类型检查,而 ESLint 则专注于代码质量和风格规范。二者协同工作,提供完整的代码质量保障:
┌─────────────────────────────────────────────────────────────┐
│ 代码质量保障体系 │
├─────────────────────────┬───────────────────────────────────┤
│ TypeScript │ ESLint │
├─────────────────────────┼───────────────────────────────────┤
│ ✓ 类型检查 │ ✓ 代码风格检查 │
│ ✓ 编译错误 │ ✓ 最佳实践建议 │
│ ✓ 类型推导 │ ✓ 潜在错误识别 │
│ ✓ 语法转换 │ ✓ 自动修复能力 │
└─────────────────────────┴───────────────────────────────────┘┌─────────────────────────────────────────────────────────────┐
│ ESLint 工具链架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Parser │───▶│ Rules │───▶│ Report │ │
│ │ 解析器 │ │ 规则集 │ │ 报告 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ AST │ │ Plugins │ │ Fix │ │
│ │ 语法树 │ │ 插件 │ │ 自动修复 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 辅助工具 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ Prettier │ Husky │ Lint-Staged │ Editor │ │
│ │ 格式化 │ 钩子 │ 暂存检查 │ 编辑器集成 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘本节代码见:ESLint Ruleset
ESLint 的工作流程包含以下核心步骤:
源代码 → 解析器(AST) → 规则检查 → 问题报告 → 自动修复(可选)| 组件 | 说明 | 常用示例 |
|---|---|---|
| Parser | 代码解析器 | @typescript-eslint/parser |
| Plugin | 规则插件包 | @typescript-eslint/eslint-plugin |
| Config | 预设配置 | plugin:@typescript-eslint/recommended |
| Rule | 单条检查规则 | @typescript-eslint/no-explicit-any |
⚠️ 版本提示:自 ESLint 9(2024 年发布)起,推荐使用 flat config(
eslint.config.js),.eslintrc.*配置文件与--ext等 CLI 参数已进入废弃流程(legacy 模式仍可通过ESLINT_USE_FLAT_CONFIG=false使用)。本文以下示例基于.eslintrc体系,适用于 ESLint 8 及兼容模式;若使用 ESLint 9+,等价的 flat config 如下:javascript// eslint.config.js(flat config,ESLint 9+) import eslint from "@eslint/js" import tseslint from "typescript-eslint" export default tseslint.config( { ignores: ["dist/**", "build/**"] }, eslint.configs.recommended, ...tseslint.configs.recommended )
使用 ESLint 官方提供的初始化工具,通过交互式问答自动生成配置:
# npm
npm init @eslint/config
# 或使用 npx
npx eslint --init交互式配置流程:
? How would you like to use ESLint?
❯ To check syntax only
To check syntax and find problems
To check syntax, find problems, and enforce code style
? What type of modules does your project use?
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
? Which framework does your project use?
❯ React
Vue.js
None of these
? Does your project use TypeScript? › Yes
? Where does your code run?
◉ Browser
◯ Node自动安装的依赖包:
- eslint # ESLint 核心
- @typescript-eslint/parser # TypeScript 解析器
- @typescript-eslint/eslint-plugin # TypeScript 规则插件
- eslint-plugin-react # React 相关规则(如果选择了 React)# npm
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# yarn
yarn add --dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# pnpm
pnpm add --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin在项目根目录创建 .eslintrc.js:
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
project: "./tsconfig.json"
},
plugins: ["@typescript-eslint"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
rules: {}
}创建 .eslintignore 文件:
# 依赖目录
node_modules/
# 构建产物
dist/
build/
out/
# 配置文件
*.config.js
*.json
# 其他文件
*.html
*.css
*.svg在 package.json 中添加:
{
"scripts": {
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
"lint:ci": "eslint src --ext .js,.jsx,.ts,.tsx --max-warnings 0"
}
}执行检查:
# 仅检查
npm run lint
# 检查并自动修复
npm run lint:fix
# CI 环境严格检查(任何警告都视为错误)
npm run lint:ci| 文件类型 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
.eslintrc.js | 可编程、支持注释 | 需要 Node.js 环境 | 复杂配置 |
.eslintrc.json | 标准 JSON 格式 | 不支持注释 | 简单配置 |
.eslintrc.yaml | 格式清晰、可读性好 | 需要 YAML 解析 | 团队协作 |
package.json | 集中管理 | 结构嵌套深 | 小型项目 |
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2022,
sourceType: "module",
project: "./tsconfig.json",
tsconfigRootDir: __dirname
}
}module.exports = {
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"prettier"
]
}extends 加载顺序: 从上到下依次加载,后面的配置会覆盖前面的。
规则配置语法:
rules: {
'rule-name': 'off' | 'warn' | 'error' | [level, options]
}规则等级说明:
| 等级 | 含义 | 退出码 |
|---|---|---|
'off' 或 0 | 关闭规则 | - |
'warn' 或 1 | 警告 | 0 |
'error' 或 2 | 错误 | 1 |
配置示例:
module.exports = {
rules: {
"no-console": "warn",
"@typescript-eslint/explicit-function-return-type": [
"error",
{
allowExpressions: true,
allowTypedFunctionExpressions: true
}
],
indent: "off",
"@typescript-eslint/indent": ["error", 2],
quotes: "off",
"@typescript-eslint/quotes": ["error", "single"],
semi: "off",
"@typescript-eslint/semi": ["error", "always"]
}
}module.exports = {
plugins: ["@typescript-eslint", "react", "import"]
}module.exports = {
env: {
browser: true,
node: true,
es2021: true,
jest: true,
mocha: true
}
}针对特定文件或目录应用不同规则:
module.exports = {
overrides: [
{
files: ["**/*.test.ts", "**/*.spec.ts"],
env: {
jest: true
},
rules: {
"@typescript-eslint/no-explicit-any": "off"
}
},
{
files: ["*.config.js", "*.config.ts"],
rules: {
"@typescript-eslint/no-var-requires": "off"
}
}
]
}module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"prettier"
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true
},
project: "./tsconfig.json"
},
plugins: ["react", "react-hooks", "@typescript-eslint", "import"],
settings: {
react: {
version: "detect"
},
"import/resolver": {
typescript: {}
}
},
rules: {
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" }
],
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling", "index"],
"newlines-between": "always",
alphabetize: { order: "asc" }
}
]
}
}module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
parser: "vue-eslint-parser",
parserOptions: {
parser: "@typescript-eslint/parser",
ecmaVersion: "latest",
sourceType: "module"
},
plugins: ["vue", "@typescript-eslint"],
rules: {
"vue/multi-word-component-names": "off",
"vue/no-v-html": "warn",
"@typescript-eslint/no-explicit-any": "warn"
}
}| 工具 | 核心功能 | 支持文件类型 | 典型规则 |
|---|---|---|---|
| ESLint | 代码质量检查 | JS, TS, JSX, TSX | no-unused-vars, no-explicit-any |
| Prettier | 代码格式化 | JS, TS, CSS, HTML, JSON, Markdown, YAML | printWidth, tabWidth, semi |
ESLint 的局限:
Prettier 的优势:
# npm
npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
# yarn
yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
# pnpm
pnpm add --save-dev prettier eslint-config-prettier eslint-plugin-prettier依赖说明:
| 包名 | 作用 |
|---|---|
prettier | Prettier 核心 |
eslint-config-prettier | 禁用 ESLint 中与 Prettier 冲突的规则 |
eslint-plugin-prettier | 将 Prettier 规则集成到 ESLint 中(可选) |
创建 .prettierrc.js:
module.exports = {
printWidth: 80,
tabWidth: 2,
semi: true,
singleQuote: true,
quoteProps: "as-needed",
jsxSingleQuote: false,
trailingComma: "es5",
bracketSpacing: true,
bracketSameLine: false,
endOfLine: "lf"
}module.exports = {
extends: ["plugin:react/recommended", "plugin:@typescript-eslint/recommended", "prettier"]
}创建 .prettierignore:
build
dist
out
node_modules{
"scripts": {
"eslint": "eslint src/** --no-error-on-unmatched-pattern --ext .js,.jsx,.ts,.tsx --cache",
"eslint:fix": "npm run eslint -- --fix",
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
"lint": "npm run eslint && npm run prettier",
"lint:fix": "npm run eslint:fix && npm run prettier:fix"
}
}即使配置了 ESLint 和 Prettier,还是可能出现每个人提交代码都不一样的情况。这是因为这些 scripts 需要手动执行,非常容易忘记或者绕过去。而如果我们能让所有开发同学每次提交代码时都自动执行一次格式化,就能确保所有人成功提交上去的代码风格一致。
Git Hooks 和 React Hooks 可不一样,它更贴近生命周期的概念,即在某一个操作前后执行的额外逻辑。
常用 Git Hooks:
| 钩子名称 | 触发时机 | 典型用途 |
|---|---|---|
pre-commit | commit 之前 | 代码格式化、lint 检查 |
commit-msg | commit 信息验证 | 检查 commit 信息规范 |
pre-push | push 之前 | 运行测试 |
pre-receive | 服务端接收前 | 服务端验证 |
Husky 简化了 Git Hooks 的配置过程。
# npm
npx husky-init && npm install
# yarn
npx husky-init && yarn
# pnpm
pnpm dlx husky-init && pnpm installnpx husky add .husky/pre-commit 'npx lint-staged'生成的 .husky/pre-commit 文件:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-stagedLint Staged 的作用是找出你添加到暂存区(git add)的文件,然后执行对应的 lint。
npm install --save-dev lint-staged
yarn add --save-dev lint-staged
pnpm install --save-dev lint-staged在 package.json 中添加:
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --cache --fix", "prettier --write --list-different"],
"*.{json,md,html,css,scss,sass,less,styl}": ["prettier --write --list-different"]
}
}配置说明:
┌─────────────────────────────────────────────────────────────┐
│ Git Hooks 工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ git commit │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ pre-commit │ │
│ │ 钩子触发 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ lint-staged │ │
│ │ 检查暂存区 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ 对暂存文件执行检查 │ │
│ ├─────────────────────────────────────────┤ │
│ │ *.ts/*.tsx → ESLint → Prettier │ │
│ │ *.css/*.json → Prettier │ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 检查通过 │ │ 检查失败 │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ commit 成功 │ │ commit 失败 │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘TypeScript ESLint 规则主要由四个部分组成:
| 分类 | 说明 | 示例规则 |
|---|---|---|
| 语法解析 | 支持 TypeScript 语法 | indent, quotes, semi |
| 语法统一 | 统一语法风格 | array-type, consistent-type-assertions |
| 类型标注 | 约束类型标注 | explicit-function-return-type, no-explicit-any |
| 能力约束 | 限制特定功能使用 | prefer-nullish-coalescing, no-unnecessary-condition |
安装配置集:
npm i eslint-config-ts-ruleset --save-dev
yarn add eslint-config-ts-ruleset --save-dev
pnpm i eslint-config-ts-ruleset --save-dev在 ESLint 配置中启用:
module.exports = {
root: true,
extends: ["plugin:@typescript-eslint/recommended", "prettier", "ts-ruleset", "ts-ruleset/strict"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json"
},
plugins: ["react", "@typescript-eslint"],
rules: {
"react/react-in-jsx-scope": "off"
}
}规则说明
统一数组的定义方式,强制使用 T[] 或 Array<T> 语法。
配置选项
'@typescript-eslint/array-type': ['error', {
default: 'array', // 默认使用 T[]
readonly: 'array', // readonly 使用 T[]
}]选项值说明
| 值 | 说明 | 示例 |
|---|---|---|
'array' | 使用 T[] 语法 | string[] |
'generic' | 使用 Array<T> 语法 | Array<string> |
'array-simple' | 简单类型用 T[],复杂类型用 Array<T> | string[], Array<{ foo: string }> |
示例
// ❌ default: 'array' 时错误
const arr: Array<string> = ["a", "b", "c"]
const readonlyArr: ReadonlyArray<string> = ["a", "b", "c"]
// ✅ 正确
const arr: string[] = ["a", "b", "c"]
const readonlyArr: readonly string[] = ["a", "b", "c"]规则说明
统一类型断言的书写方式,强制使用 as 语法或尖括号语法。
配置选项
'@typescript-eslint/consistent-type-assertions': ['error', {
assertionStyle: 'as', // 使用 as 语法
objectLiteralTypeAssertions: 'allow-as-parameter', // 对象字面量断言
}]示例
// ❌ assertionStyle: 'as' 时错误
const foo = <string>bar;
// ✅ 正确
const foo = bar as string;
// 特殊情况:在 JSX 中必须使用 as
const elem = <Component foo={bar as string} />;规则说明
统一类型定义方式,强制使用 interface 或 type。
配置选项
'@typescript-eslint/consistent-type-definitions': ['error', 'interface']示例
// ❌ 使用 'interface' 时错误
type User = {
name: string
age: number
}
// ✅ 正确
interface User {
name: string
age: number
}
// ✅ type 仍可用于联合类型、交叉类型等
type Status = "pending" | "approved" | "rejected"
type UserWithRole = User & { role: string }规则说明
在遍历数组时,如果不需要索引,推荐使用 for...of 而不是 for 循环。
示例
// ❌ 不推荐
const array = ["a", "b", "c"]
for (let i = 0; i < array.length; i++) {
console.log(array[i])
}
// ✅ 推荐
const array = ["a", "b", "c"]
for (const item of array) {
console.log(item)
}
// ✅ 需要索引时仍可使用 for 循环
for (let i = 0; i < array.length; i++) {
console.log(i, array[i])
}规则说明
推荐使用可选链操作符 ?. 替代 && 链式判断。
示例
// ❌ 不推荐
const foo = obj && obj.a && obj.a.b && obj.a.b.c
// ✅ 推荐
const foo = obj?.a?.b?.c
// ❌ 不推荐
const bar = obj && obj.method && obj.method()
// ✅ 推荐
const bar = obj?.method?.()规则说明
要求函数显式标注返回值类型。
配置选项
'@typescript-eslint/explicit-function-return-type': ['error', {
allowExpressions: true, // 允许表达式函数不标注
allowTypedFunctionExpressions: true, // 允许已类型的函数表达式不标注
allowHigherOrderFunctions: true, // 允许高阶函数不标注
allowDirectConstAssertionInArrowFunctions: true, // 允许箭头函数 const 断言
}]示例
// ❌ 错误
function foo() {
return "bar"
}
// ✅ 正确
function foo(): string {
return "bar"
}
// ✅ allowExpressions: true 时允许
const result = [1, 2, 3].map((n) => n * 2)
// ✅ 箭头函数作为变量赋值时
const add = (a: number, b: number): number => a + b规则说明
要求导出的函数和类的公共成员显式标注返回值类型。
配置选项
'@typescript-eslint/explicit-module-boundary-types': ['error', {
allowArgumentsExplicitlyTypedAsAny: true,
allowedNames: ['handler'], // 允许的函数名
}]示例
// ❌ 错误:导出的函数需要标注返回类型
export function add(a: number, b: number) {
return a + b
}
// ✅ 正确
export function add(a: number, b: number): number {
return a + b
}
// ✅ 内部函数不需要标注
function internalHelper() {
return "helper"
}规则说明
禁止在可以自动推断的地方显式标注类型。
示例
// ❌ 错误:类型可以自动推断
const foo: number = 1
const bar: string = "bar"
const baz: boolean = true
// ✅ 正确
const foo = 1
const bar = "bar"
const baz = true
// ✅ 允许显式标注(用于文档目的)
const config: MyConfig = {
/* ... */
}规则说明
禁止使用 any 类型,强制使用更具体的类型。
配置选项
'@typescript-eslint/no-explicit-any': ['error', {
fixToUnknown: true, // 自动修复为 unknown
ignoreRestArgs: true, // 允许剩余参数使用 any
}]示例
// ❌ 错误
function foo(value: any): any {
return value
}
// ✅ 正确
function foo<T>(value: T): T {
return value
}
// ✅ 使用 unknown 进行类型收窄
function process(value: unknown) {
if (typeof value === "string") {
return value.toUpperCase()
}
}
// ✅ ignoreRestArgs: true 时允许
function merge(target: any, ...sources: any[]) {
return Object.assign(target, ...sources)
}规则说明
禁止不必要的条件判断,这些判断要么总是真,要么总是假。
示例
// ❌ 错误:const 推断为字面量类型 "foo",条件总是真
const value = "foo"
if (value) {
console.log(value)
}
// ❌ 错误:类型推断已确定
function foo(value: "a" | "b") {
if (value === "a") {
return 1
} else if (value === "b") {
return 2
} else {
// ❌ 这里的 value 类型是 never
return 3
}
}
// ✅ 正确:必要的类型收窄
function bar(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase()
}
return value.toFixed(2)
}规则说明
推荐使用空值合并操作符 ?? 替代 ||,避免对 falsy 值的错误处理。
配置选项
'@typescript-eslint/prefer-nullish-coalescing': ['error', {
ignoreConditionalTests: true,
ignoreMixedLogicalExpressions: true,
}]示例
// ❌ 错误:|| 会过滤掉 0 和 ''
const foo = value || "default"
const bar = count || 10
// ✅ 正确:使用 ??
const foo = value ?? "default"
const bar = count ?? 10
// 区别说明
const a = 0 || "default" // 'default'(0 是 falsy)
const b = 0 ?? "default" // 0(0 不是 null/undefined)
const c = "" || "default" // 'default'('' 是 falsy)
const d = "" ?? "default" // ''('' 不是 null/undefined)规则说明
要求将类中不会被重新赋值的私有成员标记为 readonly(该规则只作用于类成员,不影响类外的普通变量声明)。
示例
class Cart {
// ❌ 错误:私有属性没有被重新赋值,应标记 readonly
private items: number[] = [1, 2, 3]
// ✅ 正确
private readonly items: readonly number[] = [1, 2, 3]
// ✅ 会被重新赋值的成员不需要 readonly
private total = 0
add(n: number) {
this.total += n
}
}规则说明
强制在条件语句中使用布尔值,避免隐式类型转换。
配置选项
'@typescript-eslint/strict-boolean-expressions': ['error', {
allowString: false, // 不允许字符串隐式转换
allowNumber: false, // 不允许数字隐式转换
allowNullableObject: true, // 允许可空对象检查
}]示例
// ❌ 错误:隐式转换
const value: string = "foo"
if (value) {
console.log(value)
}
// ✅ 正确:显式检查
if (value.length > 0) {
console.log(value)
}
// ❌ 错误:数字隐式转换
const count: number = 0
if (count) {
console.log(count)
}
// ✅ 正确:显式检查
if (count > 0) {
console.log(count)
}
// ✅ allowNullableObject: true 时允许
const obj: string | null = null
if (obj) {
// 检查 null/undefined
console.log(obj)
}规则说明
要求 Promise 必须被正确处理(await、catch 或 void)。
配置选项
'@typescript-eslint/no-floating-promises': ['error', {
ignoreVoid: true, // 允许使用 void 忽略
ignoreIIFE: true, // 允许 IIFE 形式
}]示例
// ❌ 错误:Promise 未被处理
async function fetchData() {
return fetch("/api/data")
}
fetchData() // Promise 被忽略
// ✅ 正确:使用 await
async function main() {
await fetchData()
}
// ✅ 正确:使用 catch
fetchData().catch(console.error)
// ✅ 正确:使用 void(ignoreVoid: true)
void fetchData()
// ✅ 正确:使用 then
fetchData().then(console.log)规则说明
只对 Thenable 类型(Promise)使用 await,避免不必要的 await。
示例
// ❌ 错误:对非 Promise 使用 await
async function foo() {
const value = await 42
const text = await "hello"
}
// ✅ 正确
async function foo() {
const value = 42
const text = "hello"
}
// ✅ 正确:对 Promise 使用 await
async function bar() {
const response = await fetch("/api/data")
const data = await response.json()
}规则说明
禁止在条件语句中使用 Promise,因为 Promise 对象总是 truthy。
配置选项
'@typescript-eslint/no-misused-promises': ['error', {
checksConditionals: true,
checksVoidReturn: true,
}]示例
// ❌ 错误:Promise 在条件中总是 truthy
async function checkPermission() {
return true
}
if (checkPermission()) {
// 忘记 await
console.log("allowed")
}
// ✅ 正确
if (await checkPermission()) {
console.log("allowed")
}
// ❌ 错误:Promise 回调不应该是 async
;[1, 2, 3].forEach(async (item) => {
await processItem(item)
})
// ✅ 正确:使用 for...of
for (const item of [1, 2, 3]) {
await processItem(item)
}| 规则 | 说明 | 推荐等级 |
|---|---|---|
@typescript-eslint/array-type | 统一数组定义方式 | ⭐⭐⭐ |
@typescript-eslint/consistent-type-assertions | 统一类型断言方式 | ⭐⭐⭐⭐ |
@typescript-eslint/consistent-type-definitions | 统一类型定义方式 | ⭐⭐⭐ |
@typescript-eslint/prefer-for-of | 推荐使用 for...of | ⭐⭐⭐ |
@typescript-eslint/prefer-optional-chain | 推荐使用可选链 | ⭐⭐⭐⭐⭐ |
| 规则 | 说明 | 推荐等级 |
|---|---|---|
@typescript-eslint/no-explicit-any | 禁止 any 类型 | ⭐⭐⭐⭐⭐ |
@typescript-eslint/no-unnecessary-condition | 禁止不必要条件 | ⭐⭐⭐⭐ |
@typescript-eslint/prefer-nullish-coalescing | 推荐空值合并 | ⭐⭐⭐⭐ |
@typescript-eslint/strict-boolean-expressions | 严格布尔检查 | ⭐⭐⭐ |
@typescript-eslint/no-floating-promises | Promise 必须处理 | ⭐⭐⭐⭐⭐ |
@typescript-eslint/await-thenable | 只对 Promise await | ⭐⭐⭐⭐ |
@typescript-eslint/no-misused-promises | 禁止误用 Promise | ⭐⭐⭐⭐⭐ |
A:
两者互补,建议同时使用。
A: 使用 eslint-config-prettier 禁用冲突规则:
module.exports = {
extends: [
"plugin:@typescript-eslint/recommended",
"prettier" // 必须放在最后
]
}A: 添加 CI 脚本:
{
"scripts": {
"lint:ci": "eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0"
}
}--max-warnings 0 确保任何警告都会导致 CI 失败。
A: 使用注释:
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const value: any = JSON.parse(data)
/* eslint-disable @typescript-eslint/no-explicit-any */
const a: any = 1
const b: any = 2
/* eslint-enable @typescript-eslint/no-explicit-any */A:
@types/package-namedeclarations.d.ts:declare module "untyped-package" {
const value: any
export default value
}parserOptions.project?A: 某些规则(如 no-floating-promises)需要类型信息才能工作。这些规则被称为"类型感知规则"。
parserOptions: {
project: './tsconfig.json',
}A: 创建共享配置包:
// packages/eslint-config/index.js
module.exports = {
extends: ["plugin:@typescript-eslint/recommended", "prettier"],
rules: {
// 共享规则
}
}
// packages/app/.eslintrc.js
module.exports = {
extends: ["@my-org/eslint-config"]
}// .eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"prettier"
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
project: "./tsconfig.json"
},
plugins: ["@typescript-eslint"],
rules: {
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_"
}
],
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/await-thenable": "error"
}
}┌─────────────────────────────────────────────────────────────┐
│ 规则启用策略 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 第一阶段:基础规则 │
│ ├── plugin:@typescript-eslint/recommended │
│ └── 解决所有 error 级别问题 │
│ │
│ 第二阶段:类型感知规则 │
│ ├── 添加 parserOptions.project │
│ ├── plugin:@typescript-eslint/recommended-requiring-type │
│ └── 解决类型相关问题 │
│ │
│ 第三阶段:严格规则 │
│ ├── no-explicit-any: error │
│ ├── no-floating-promises: error │
│ └── 其他团队约定规则 │
│ │
└─────────────────────────────────────────────────────────────┘// .vscode/settings.json
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"]
}// .vscode/extensions.json
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"editorconfig.editorconfig"
]
}最后更新时间:2026-02-15